"""
Author: Jian SuiYue kaohx0214@yeah.net
Date: 2025-04-25 17:25:43
LastEditTime: 2025-05-15 17:12:48
FilePath: LibraryManagerStudio/web/middlewares.py
"""

from loguru import logger
import time
from uuid import uuid4

from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware


async def request_handler_middleware(request: Request, call_next):
    """
    Process request middleware
    Responsible to recoding request logs, performance tracking and adding reponse headers。
    """
    # Generate Reuqest ID use to tracking
    request_id = str(uuid4())

    # 记录请求开始信息
    start_time = time.time()
    client_ip = request.client.host if request.client else "unknown"
    logger.info(
        f"Start Processing request [ID:{request_id}] {request.method} {request.url.path} "
        f"- Client: {client_ip}"
    )

    try:
        # 处理请求
        response = await call_next(request)

        # 计算处理时间
        process_time = time.time() - start_time

        # 添加自定义响应头
        response.headers["X-Request-ID"] = request_id
        response.headers["X-Processing-Time"] = str(process_time)

        # 记录请求完成信息
        logger.info(
            f"Finish Request [ID:{request_id}] {request.method} {request.url.path} "
            f"- status code: {response.status_code} - processing time: {process_time:.4f} second"
        )

        return response

    except Exception as e:
        # 记录异常信息
        process_time = time.time() - start_time
        logger.error(
            f"Error while processing request [ID:{request_id}] {request.method} {request.url.path} "
            f"- error msg: {str(e)} - processing time: {process_time:.4f} second",
            exc_info=True
        )

        # 重新抛出异常，让FastAPI的异常处理器处理
        raise


class LoggingMiddleware(BaseHTTPMiddleware):
    """
    The logegr middileware base on class.
    Provide the same functionality as function middleware,
    but implemented using the BaseHTTPMiddleware class.
    """

    async def dispatch(self, request: Request, call_next):
        """
        dispatch the request message and display it.
        """
        # generate id for tracking request
        request_id = str(uuid4())

        # 记录请求开始信息
        start_time = time.time()
        client_ip = request.client.host if request.client else "unknown"
        logger.info(
            f"Start processing the request [ID:{request_id}] {request.method} {request.url.path} "
            f"- Client: {client_ip}"
        )

        try:
            # 处理请求
            response = await call_next(request)

            # 计算处理时间
            process_time = time.time() - start_time

            # 添加自定义响应头
            response.headers["X-Request-ID"] = request_id
            response.headers["X-Processing-Time"] = str(process_time)

            # 记录请求完成信息
            logger.info(
                f"Finish request [ID:{request_id}] {request.method} {request.url.path} "
                f"- status code: {response.status_code} - processing time: {process_time:.4f}second"
            )

            return response

        except Exception as e:
            # 记录异常信息
            process_time = time.time() - start_time
            logger.error(
                f"Error: while processing the request [ID:{request_id}] {request.method} {request.url.path} "
                f"- error msg: {str(e)} - processing time: {process_time:.4f}second",
                exc_info=True
            )

            # re raise expcetion, let FastAPI application expcetion manager to process
            raise
